﻿Public Module WikiPageModels


    Public MustInherit Class SideboxField

        Public MustOverride ReadOnly Property HasFieldText As Boolean

        Public Overridable ReadOnly Property FieldText As String
            Get
                Return ""
            End Get
        End Property

        Public MustOverride Function GetContent(HtmlHelper As HtmlHelper) As String

    End Class

    Public Class SideboxImageField
        Inherits SideboxField

        Property PictureUrl As String

        Sub New(PictureUrl As String)
            Me.PictureUrl = PictureUrl
        End Sub


        Public Overrides ReadOnly Property HasFieldText As Boolean
            Get
                Return False
            End Get
        End Property

        Public Overrides Function GetContent(HtmlHelper As HtmlHelper) As String
            Dim resolvedImageUrl As String = ProcessImageUrl(PictureUrl, HtmlHelper.ViewContext.RequestContext.HttpContext.Request.Url.Host)
            Dim scaledImageUrl As String = ProcessImageUrl(PictureUrl, HtmlHelper.ViewContext.RequestContext.HttpContext.Request.Url.Host, 400, 300)
            Return String.Format("<center><a href='{0}'><img class='sidebox-image' src='{1}'></a><center>", HttpUtility.UrlPathEncode(resolvedImageUrl), HttpUtility.UrlPathEncode(scaledImageUrl))
        End Function
    End Class

    Public Class SideboxTitleField
        Inherits SideboxField

        Property Title As String
        Property PageType As String

        Sub New(Title As String, PageType As String)
            Me.Title = Title
            Me.PageType = PageType
        End Sub


        Public Overrides ReadOnly Property HasFieldText As Boolean
            Get
                Return False
            End Get
        End Property

        Public Overrides Function GetContent(HtmlHelper As HtmlHelper) As String
            Return String.Format("<h4 class='sidebox-title'>{0}: {1}</h4>", Wiki.WikiModel.CreateInnerLink(PageType, PageType, Title, HtmlHelper), Title)
        End Function
    End Class

    Public Class SideboxCenteredTextField
        Inherits SideboxField

        Property Text As String

        Sub New(Text As String)
            Me.Text = Text
        End Sub

        Public Overrides ReadOnly Property HasFieldText As Boolean
            Get
                Return False
            End Get
        End Property

        Public Overrides Function GetContent(HtmlHelper As HtmlHelper) As String
            Return String.Format("<center>{0}</center>", Text)
        End Function
    End Class

    Public Class SideBoxTagGroupField
        Inherits SideboxField

        Private GroupName As String
        Private Tags As StringSet
        Private ParentPageModel As WikiPageModel

        Public Overrides Function GetContent(HtmlHelper As HtmlHelper) As String
            Dim Builder As New StringBuilder
            For Each tag In Tags
                If Builder.Length > 0 Then Builder.Append(", ")
                Builder.Append(WikiModel.CreateInnerLink(tag, tag, ParentPageModel.Title, HtmlHelper))
            Next
            Return Builder.ToString()
        End Function
        Public Overrides ReadOnly Property FieldText As String
            Get
                Return GroupName
            End Get
        End Property

        Public Overrides ReadOnly Property HasFieldText As Boolean
            Get
                Return True
            End Get
        End Property

        Public Sub New(GroupName As String, Tags As IEnumerable(Of String), ParentPageModel As WikiPageModel)
            Me.GroupName = GroupName
            Me.Tags = Tags
            Me.ParentPageModel = ParentPageModel
        End Sub
    End Class

    Public Class SideBoxNamesField
        Inherits SideboxField

        Private Names As IEnumerable(Of String)
        Private ParentPageModel As WikiPageModel

        Public Overrides Function GetContent(HtmlHelper As HtmlHelper) As String
            Dim Builder As New StringBuilder
            Dim first As Boolean = True
            Builder.AppendLine("<small>")
            For Each name In Names
                If Not first Then
                    Builder.Append(", ")
                Else
                    first = False
                End If
                Builder.Append(WikiModel.CreateInnerLink(name, name, ParentPageModel.Title, HtmlHelper))
            Next
            Builder.AppendLine("</small>")
            Return Builder.ToString()
        End Function

        Public Overrides ReadOnly Property HasFieldText As Boolean
            Get
                Return False
            End Get
        End Property

        Public Sub New(Names As IEnumerable(Of String), ParentPageModel As WikiPageModel)
            Me.Names = Names
            Me.ParentPageModel = ParentPageModel
        End Sub
    End Class

    Public Class SideBoxNutritionalDataField
        Inherits SideboxField

        Private NutritionData As NutritionalData

        Public Overrides Function GetContent(HtmlHelper As HtmlHelper) As String
            Return HtmlHelper.Partial("NutritionalData", NutritionData).ToString()
        End Function


        Public Sub New(NutritionData As NutritionalData)
            Me.NutritionData = NutritionData
        End Sub

        Public Overrides ReadOnly Property HasFieldText As Boolean
            Get
                Return False
            End Get
        End Property
    End Class


    Public MustInherit Class WikiPageModel
        Public Overridable Property Title As String

        Public MustOverride Function GetFooterText() As String

        Public MustOverride Function GetSideboxFields() As List(Of SideboxField)

        Public MustOverride Function GetViewName() As String

    End Class

    Public MustInherit Class VirtualWikiPageModel
        Inherits WikiPageModel

        Public Sub New(PageTitle As String)
            Me.Title = PageTitle
        End Sub

        Public Overrides Function GetFooterText() As String
            Return "דף זה יוצר אוטומטית"
        End Function

        Public Overrides Function getSideboxFields() As List(Of SideboxField)
            Return New List(Of SideboxField)
        End Function

    End Class

    Public Class WikiPageCompersionModel
        Public Property PageOld As FiledWikiPageModel
        Public Property PageNew As FiledWikiPageModel

        Public ReadOnly Property Title As String
            Get
                If PageOld.Title <> PageNew.Title Then Throw New Exception("WTF?")
                Return PageNew.Title
            End Get
        End Property

        Sub New(PageOld As FiledWikiPageModel, PageNew As FiledWikiPageModel)
            Me.PageOld = PageOld
            Me.PageNew = PageNew
        End Sub
    End Class

    <Serializable> Public Class FiledWikiPageModel
        Inherits WikiPageModel
        Public Overrides Function GetViewName() As String
            Return "WikiPage"
        End Function

        Public Overrides Property Title As String
            Get
                Return MyBase.Title
            End Get
            Set(value As String)
                For Each c In WikiModel.InvalidChars
                    If value.Contains(c) Then Throw New WikiInvalidNameException(String.Format("Invalid char ({0}) in page name ({1})", c, Title))
                Next
                MyBase.Title = StrConv(value, VbStrConv.ProperCase)
                AddName(MyBase.Title)
            End Set
        End Property

        Private _Names As New StringSet
        Public Property Names As HashSet(Of String)
            Get
                Return _Names
            End Get
            Set(value As HashSet(Of String))
                _Names.Clear()
                AddName(MyBase.Title)
                For Each name In value
                    AddName(StrConv(name, VbStrConv.ProperCase).Trim())
                Next
            End Set
        End Property

        Public Property NamesString As String
            Get
                Return _Names.ToString
            End Get
            Set(value As String)
                If value Is Nothing Then value = ""
                Names = New StringSet(value)
            End Set
        End Property
        Public Property Content As String
        Public Property DateModeified As Date
        Public Property VersionNumber As Integer
        Public Property LastAuthor As String
        Public Property LastChangeNotes As String
        Public Property Deleted As Boolean
        Public Property IsCategory As Boolean
        Public Property Picture As String
        Public Property PageType As String

        Private _Tags As SerializableDictionary(Of String, StringSet)
        Property Tags As SerializableDictionary(Of String, StringSet)
            Get
                If _Tags Is Nothing Then _Tags = New SerializableDictionary(Of String, StringSet)
                Return _Tags
            End Get
            Set(value As SerializableDictionary(Of String, StringSet))
                _Tags = New SerializableDictionary(Of String, StringSet)
                For Each tagGroup In value
                    If tagGroup.Value.Count > 0 Then
                        _Tags.Add(tagGroup.Key, tagGroup.Value)
                    End If
                Next
            End Set
        End Property
        Public Property TagsStrings As SerializableDictionary(Of String, String)
            Get
                Dim d As New SerializableDictionary(Of String, String)()
                For Each tag In _Tags
                    d(tag.Key) = tag.Value.ToString()
                Next
                Return d
            End Get
            Set(value As SerializableDictionary(Of String, String))
                _Tags = New SerializableDictionary(Of String, StringSet)()
                For Each tag In value
                    Dim s As String = Trim(Regex.Replace(tag.Value, "\s*[,;]\s*", ","))
                    If s <> "" Then _Tags(tag.Key) = s
                Next
            End Set
        End Property

        Public Property IsFavorite As Boolean

        <NonSerialized()> Private _IsArchivedVersion
        Public Property IsArchivedVersion As Boolean
            Get
                Return _IsArchivedVersion
            End Get
            Set(value As Boolean)
                _IsArchivedVersion = value
            End Set
        End Property
        Public ReadOnly Property IsCurrentVersion As Boolean
            Get
                Return Not _IsArchivedVersion
            End Get
        End Property

        Public Property NutritionalData As NutritionalData

        '-----

        Public Sub AddName(Name As String)
            _Names.Add(Name.Trim())
        End Sub
        Public Sub RemoveName(Name As String)
            Name = StrConv(Name, VbStrConv.ProperCase).Trim()
            If Name = Me.Title Then Throw New Exception("Cannot remove name which is used as title")
            If _Names.Contains(Name) Then
                _Names.Remove(Name)
            End If
        End Sub

        Public Sub New(Title As String)
            Me.New()
            Me.Title = Title
            Me.Content = ""
            Me.PageType = WikiModel.Instance.DefaultPageType
        End Sub

        Sub New()
            Me._Tags = New SerializableDictionary(Of String, StringSet)
            Me.Content = ""
        End Sub

        Public Overrides Function GetFooterText() As String
            Return String.Format("גרסה {0}. השתנה לאחרונה ב{1 :U} על ידי {2}", VersionNumber, DateModeified, LastAuthor)
        End Function
        Public Function GetVersionCode() As Long
            Return DateModeified.Ticks \ TimeSpan.TicksPerSecond
        End Function
        Public Function HasNonTitleNames() As Boolean
            Return Names.Count > 1
        End Function
        Public Function GetNonTitleNames() As StringSet
            Dim NonTitleNames As New StringSet(Names)
            NonTitleNames.Remove(Title)
            Return NonTitleNames
        End Function

        Public Overrides Function GetSideboxFields() As List(Of SideboxField)
            Dim fields As New List(Of SideboxField)
            fields.Add(New SideboxTitleField(Title, PageType))
            If Picture IsNot Nothing And Picture <> "" Then fields.Add(New SideboxImageField(Picture))
            For Each TagGroup In Tags
                If TagGroup.Value.Count > 0 Then fields.Add(New SideBoxTagGroupField(TagGroup.Key, TagGroup.Value, Me))
            Next
            If NutritionalData IsNot Nothing AndAlso NutritionalData.Valid Then
                fields.Add(New SideBoxNutritionalDataField(NutritionalData))
            End If
            If Names.Count > 1 Then
                fields.Add(New SideBoxNamesField(Names, Me))
            End If
            Return fields
        End Function

        Function GetAllTags() As HashSet(Of String)
            Dim AllTags As New HashSet(Of String)
            For Each tagGroup In Me.Tags.Values
                AllTags.UnionWith(tagGroup)
            Next
            AllTags.Add(Me.PageType)
            If Me.IsFavorite Then AllTags.Add("מועדפים")
            Return AllTags
        End Function

    End Class

    Public Class VirtualDisambiguationPageModel
        Inherits VirtualWikiPageModel

        Public Property Pages As List(Of String)

        Public Sub New(pageName As String, pages As List(Of String))
            MyBase.New(pageName)
            Me.Pages = pages
        End Sub

        Public Overrides Function GetViewName() As String
            Return "WikiDisambiguationPage"
        End Function
    End Class


End Module
